﻿using Autofac;
using Autofac.Extras.DynamicProxy;
using Microsoft.AspNetCore.Http;
using RayD.Core;
using RayD.Repository;
using RayD.Repository.DB;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Autofac.Extras.Quartz;

namespace RayD.App.Setup
{
    public class AutofacModuleRegister : Autofac.Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            var basePath = AppContext.BaseDirectory;

            #region 注册拦截器
            // AOP 开关，如果想要打开指定的功能，只需要在 appsettigns.json 对应对应 true 就行。
            var typeList = new List<Type>();
            if (AppSettings.MiniProfilerAOP.Enabled)
            {
                builder.RegisterType<ApiMiniProfilerInterceptor>();           //可以直接替换其他拦截器
                typeList.Add(typeof(ApiMiniProfilerInterceptor));             //性能分析切面
            }
            if (AppSettings.CacheAOP.Enabled)
            {
                builder.RegisterType<CacheInterceptor>();                     //这样可以注入第二个
                typeList.Add(typeof(CacheInterceptor));                       //缓存切面
            }
            #endregion

            #region 注册仓储应用服务
            // 仓储注册
            switch (AppSettings.DefaultDb.DataBaseType)
            {
                case DataBaseType.SqlServer:
                    builder.RegisterType<SqlServerDataBase>().As<IDatabase>()
                       .AsImplementedInterfaces()
                       .InstancePerDependency();
                    break;
                case DataBaseType.Oracle:
                    builder.RegisterType<OracleDataBase>().As<IDatabase>()
                       .AsImplementedInterfaces()
                       .InstancePerDependency();
                    break;
                case DataBaseType.MySql:
                    builder.RegisterType<MySqlDataBase>().As<IDatabase>()
                       .AsImplementedInterfaces()
                       .InstancePerDependency();
                    break;
                default:
                    builder.RegisterType<MySqlDataBase>().As<IDatabase>()
                       .AsImplementedInterfaces()
                       .InstancePerDependency();
                    break;
            }
            builder.RegisterType<BaseRepository>().As<IRepository>()
               .AsImplementedInterfaces()
               .InstancePerDependency();

            // 应用注册，并使服务能够被拦截（AOP）
            var appDllFile = Path.Combine(basePath, $"{Define.APP_PROJNAME}.dll");
            if (!File.Exists(appDllFile))
            {
                var msg = $"{Define.APP_PROJNAME}.dll 丢失，因为项目解耦了，所以需要先F6编译，再F5运行，请检查 bin 文件夹，并拷贝。";
                throw new Exception(msg);
            }
            builder.RegisterAssemblyTypes(Assembly.LoadFrom(appDllFile))
               .InstancePerLifetimeScope()   //相当于Scope
               .EnableClassInterceptors()//引用Autofac.Extras.DynamicProxy;
               .InterceptedBy(typeList.ToArray());//允许将拦截器服务的列表分配给注册。
            #endregion

            #region 注册没有接口的类，启用class代理拦截

            //注意如果使用没有接口的服务，并想对其使用 AOP 拦截，就必须设置为虚方法
            //只能注入该类中的虚方法，且必须是public
            //builder.RegisterAssemblyTypes(Assembly.GetAssembly(typeof(Love)))
            //    .EnableClassInterceptors()
            //    .InterceptedBy(cacheType.ToArray());
            #endregion

            #region 注册含有接口的类，启用interface代理拦截

            //不用虚方法
            //builder.RegisterType<AopService>().As<IAopService>()
            //   .AsImplementedInterfaces()
            //   .EnableInterfaceInterceptors()
            //   .InterceptedBy(typeof(BlogCacheAOP));
            #endregion

            //HttpContext
            builder.RegisterType(typeof(HttpContextAccessor)).As(typeof(IHttpContextAccessor))
                .SingleInstance();

            //Quartz实现IJob对象的服务
            if (AppSettings.JobOption.Enabled)
            {
                var jobDllFile = Path.Combine(basePath, $"{Define.APPEXTRA_PROJNAME}.dll");
                if (!File.Exists(jobDllFile))
                {
                    var msg = $"{Define.APPEXTRA_PROJNAME}.dll 丢失，因为项目解耦了，所以需要先F6编译，再F5运行，请检查 bin 文件夹，并拷贝。";
                    throw new Exception(msg);
                }
                builder.RegisterModule(new QuartzAutofacFactoryModule());
                builder.RegisterModule(new QuartzAutofacJobsModule(Assembly.LoadFrom(jobDllFile))); 
            }

            // 获取容器
            builder.RegisterBuildCallback(container => ServiceContainer.Initialize((IContainer)container));
        }
    }
}
